//*****************************************************************************
//*****************************************************************************
// 		RF Link Control Interface Code
//
//****************************************************************************



//=============================================================================
//	API name:	configure_RFLM_State
//=============================================================================

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 		Subroutine: configure_RFLM_State
//		use this subroutine to initialize the RF Link Manager state
//		and the RF Physical Interface with the RFmodule.
//		r0	= in: RF Link Manager State
//		r6	= in: return address
//		r7	= inout: stack pointer
//		API Status Variables Updated: RFLM_State, SRCI_SV_RFLM_LinkMode,
//			SRCI_SV_RFLM_Slot0_ConnectionStatus,SRCI_SV_RFLM_Slot1_ConnectionStatus
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
configure_RFLM_State:
		st	r0,sp,0
		st	r1,sp,1
		st	r2,sp,2
		st	r3,sp,3
		st	r4,sp,4
		st	r5,sp,5
		st	r6,sp,6
		add	sp,sp,7

		sub	r1,r0,_RFLM_InitializedSleepState
		bc	EQ,RFLM_InitializedSleep

		sub	r1,r0,_RFLM_SleepState
		bc	EQ,RFLM_Sleep
		
		sub	r1,r0,_RFLM_StandbyState
		bc	EQ,RFLM_Standby

		sub	r1,r0,_RFLM_ActiveState
		bc	EQ,RFLM_Active

	configure_RFLM_State_end:

		sub	sp,sp,7
		ld	r0,sp,0
		ld	r1,sp,1
		ld	r2,sp,2
		ld	r3,sp,3
		ld	r4,sp,4
		ld	r5,sp,5
		ld	r6,sp,6
		jsr	r6,r6


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 		StateHandler: RFLM_InitializedSleep
//		use this code to initialize the RF Link Manager
//		and the RF Physical Interface with the RFmodule into a known reset state
//		and then place the RF Link Manager into RFLM_Sleep mode.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RFLM_InitializedSleep:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 		StateHandler: RFLM_Sleep
//		use this code to place the RF Link Manager and RFM into a low
//		power sleep state.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RFLM_Sleep:

//-----------------------------------------------
//stop the two RF Link Threads
		jsr	r6,stop_RFLMthreads

//check to see if there is any Hardware blocking that must be taken care of when these threads are stopped
		mov	r0,1<<_RFLM_semaphore		//0b10
		outp	r0,SCUup
		outp	r0,SCUup
		
//-----------------------------------------------
//Setup BBU direction pin
		mov	r0,0
		outp	r0,BBU0cfg0

		inp	r0,GPHcfg
		bis	r0,r0,_BBUdirection + 8
		bic	r0,r0,_BBUdirection
		outp	r0,GPHcfg

//-----------------------------------------------
//enable the I/O interface between XInC and the CC200
		mov	r0,((1<<_CC2400_TX|1<<_CC2400_RX|1<<_CC2400_CSn)<< 8 | (1<<_CC2400_CSn))
		outp	r0,GPEcfg

		mov	r0,0b0000000000001011		//SCK = system/16
		outp	r0,SPI1cfg
	
//-----------------------------------------------
//power up reset of CC2400	
		mov	r1,0x00
		mov	r2,0x0000
		jsr	r6,put_CC2400_register
		
		mov	r1,_MANAND_regAddr
		mov	r2,0x7FFF
		jsr	r6,put_CC2400_register
	
		mov	r1,0x00
		mov	r2,0x8000
		jsr	r6,put_CC2400_register	
		
	//Initialize the CC2400's registers
		jsr	r6, put_CC2400_state

	//turn off oscillator of CC2400
		mov	r1, _SXOSCOFF_regAddr
		jsr	r6, put_CC2400_Strobe
		
//-----------------------------------------------
//If we are already in the sleep state then do nothing
		ld	r0,RFLM_State
		sub	r0,r0,_RFLM_InitializedSleepState
		bc	EQ,RFLM_InitializedSleep10
//we are now in sleep state so lets not bother making the table so we don't waste power

		mov	r0,_RFLM_SleepState
		st	r0,RFLM_State
		bra	configure_RFLM_State_end
//-----------------------------------------------



RFLM_InitializedSleep10:
//-----------------------------------------------
//generate the RFchannelRegisterTable_even table
//make_RFchannelRegisterTable_even:
//		mov	r5,38					//loop counter
//		mov	r4,RFchannelRegisterTable_odd
//		mov	r3,_RFchannel0_odd

//	make_RFchannelRegisterTable_even_10:
//		rol	r0,r3,4				//Left justify
//		st	r0,r4,0
//		add	r4,r4,1
//		add	r3,r3,2				//increment PLL channel configuration

//		sub	r5,r5,1
//		bc	ZC,make_RFchannelRegisterTable_even_10


		mov	r0,_RFLM_InitializedSleepState
		st	r0,RFLM_State

		bra	configure_RFLM_State_end








//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 		StateHandler: RFLM_Standby
//		use this code to place the RF Link Manager and RFM into a low
//		power standby state.
//		the registers are programmed with a default configuration
//		r6	= in: return address
//		r7	= inout: stack pointer
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
RFLM_Standby:


//-----------------------------------------------
//If we are already in the standby state then do nothing
		ld	r0,RFLM_State
		sub	r0,r0,_RFLM_StandbyState
		bc	EQ,configure_RFLM_State_end
	//ok up to here
		ld	r0,RFLM_State
		sub	r1,r0,_RFLM_SleepState
		bc	EQ,RFLM_Standby_fromSleep
	//ok up to here
		
		sub	r1,r0,_RFLM_InitializedSleepState
		bc	EQ,RFLM_Standby_fromSleep
		
	//DOESN"T REACH THIS POINT
	
		
	
	RFLM_Standby_fromActive:
//-----------------------------------------------
//stop the two RF Link Manager Threads
		jsr	r6,stop_RFLMthreads
//		mov	r0,1<<_RFLM_semaphore		//0b10
//		outp	r0,SCUup
//		outp	r0,SCUup



//=========================================
//Switch CC2400 back to idle state
		inp	r0, GPEin
		bis	r0, r0, _CC2400_RX
		outp	r0, GPEout					//switch to state FS_On[9]
                      
		inp	r0, GPEin
		bic	r0, r0, _CC2400_TX
		outp	r0, GPEout
		rol	r0, r0, 0
		bic	r0, r0, _CC2400_RX	
		outp	r0, GPEout					//put CC2400 in state IDLE[1]		
				
		bra	RFLM_Standby10
//=========================================
		

//===================================
	RFLM_Standby_fromSleep:

	//Start CC2400 oscillator
		mov	r1, _SXOSCON_regAddr
		jsr	r6, put_CC2400_Strobe
	
	//Wait for oscillator to stablilize
	RFM_WiatForOscillator:
	
		mov	r1, 0x80
		jsr	r6, get_CC2400_status		
		
		bix	r1, r1, 6	
		bc	VC, RFM_WiatForOscillator
		
//		mov	r1,_MANAND_regAddr
//		mov	r2,0x7FFF
//		jsr	r6,put_CC2400_register
	
		bra	RFLM_Standby10
		rol	r0,r0,0		//support for legacy assembler
//==================================
RFLM_Standby10:

//-----------------------------------------------
//disable the BBU for low power
		mov	r0,0
		outp	r0,BBU0cfg0

//-----------------------------------------------
//_RFLinkManager_ThreadA setup with semaphore protection on SCU access
		mov   r0,RFLinkManager_ThreadA_SP
		mov   r1,RFLinkManager_ThreadA_enter
		mov   r2,_RFLinkManager_ThreadA<<3 | 7	//set pointer to Thread7, Register7
		mov	r3,1<<_SCU_semaphore
		outp	r3,SCUdown
		outp  r2,SCUpntr
		outp  r1,SCUpc					//set Program counter
		outp	r0,SCUreg					//set Stack Pointer
		outp	r3,SCUup

		mov	r0,_RFLM_StandbyState
		st	r0,RFLM_State
		
		
		
		bra	configure_RFLM_State_end


RFLM_Active:
//-----------------------------------------------
//If we are already in the active state then do nothing
		ld	r0,RFLM_State
		sub	r0,r0,_RFLM_ActiveState
		bc	EQ,configure_RFLM_State_end

//-----------------------------------------------
//enable the BBU
	//configure the BBU baud rate	for 1.152 Mbps
#ifdef _RFclkFromPLL
		mov	r0,08191
#else
	#ifdef	_18.432MHz
		mov	r0,12287					// 11999 for 18 MHz; 12287  for 18.432MHz
	#else
		mov	r0,11999
	#endif
#endif
		outp	r0,BBU0brg					//setup baud rate
		
		mov	r0,0x217B
		outp	r0,BBU0start	

		inp	r0,GPHin
		bic	r0,r0,_BBUdirection			//BBUtx pin is input
		outp	r0,GPHout


		mov	r0,300<<8

		outp	r0,BBU0cfg1
				
		mov	r0,0b0001000001100011
		outp	r0,BBU0cfg0						//enable BBU

//-----------------------------------------------
//generate "random" number
//		inp	r0,SCXcount				//12 bit RC clock counter
//		ld	r1,RFLP_ActiveStateCounter
//		add	r1,r1,1
//		st	r1,RFLP_ActiveStateCounter
//		add	r0,r0,r1

//		inp	r1,BBU0time
//		add	r0,r0,r1
//make the 12 bit RFLP_MstrSessionID "random"
//		and	r0,r0,0x0FFF
//		st	r0,RFLP_MstrSessionID

//calculate the expected response to the RFLP_MstrSessionID using the very complex algorithm below
//		add	r0,r0,11
//		and	r0,r0,0x0FFF
//		st	r0,RFLP_MstrSessionID_ChallengeResponse

//-----------------------------------------------
//start the main RF Link Manager Thread
		mov	r3,1<<_SCU_semaphore
		outp	r3,SCUdown
		ld	r2,SCUstop_status
		bic	r2,r2,_RFLinkManager_ThreadA
		st	r2,SCUstop_status
		outp	r2,SCUstop
		outp	r3,SCUup

	RFLM_Active_finish:
		ld	r0,RFLM_State
		sub	r0,r0,_RFLM_ActiveState
		bc	NE,RFLM_Active_finish

		bra	configure_RFLM_State_end


//-----------------------------------------------
//stop the two RF Link Manager Threads
stop_RFLMthreads:
		mov	r1,1<<_SCU_semaphore
		outp	r1,SCUdown
		ld	r2,SCUstop_status
		bis	r2,r2,_RFLinkManager_ThreadA
		bis	r2,r2,_RFLinkManager_ThreadB
		st	r2,SCUstop_status
		outp	r2,SCUstop
		outp	r1,SCUup
		jsr	r6,r6









//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 		crcLoop_method:
//		This subroutine computes the CRC-8 of one data byte using the standard loop method
//		r3	= trashed
//		r4	= in: data byte
//		r5	= inout: CRC-8 register
//		r6	= in:	return address
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
crcLoop_method:
		mov	r3,8					//bit counter
		rol	r4,r4,8				//left justify
	crcLoop:
		add	r5,r5,r5				//shift left
		bic	r5,r5,8
		bc	VS,carrySet_reg
		add	r4,r4,r4				//shift left
		bc	CS,carrySet_data
		bic	r5,r5,0
		sub	r3,r3,1
		bc	ZC,crcLoop
		jsr	r6,r6					//return
carrySet_data:
		bis	r5,r5,0
		sub	r3,r3,1
		bc	ZC,crcLoop
		jsr	r6,r6					//return
carrySet_reg:
		add	r4,r4,r4				//shift left
		bc	CS,carrySet_data10
		bic	r5,r5,0
		xor	r5,r5,CRC_polynomial
		sub	r3,r3,1
		bc	ZC,crcLoop
		jsr	r6,r6					//return
carrySet_data10:
		bis	r5,r5,0
		xor	r5,r5,CRC_polynomial		//xor polynomial
		sub	r3,r3,1
		bc	ZC,crcLoop
		jsr	r6,r6					//return
